#ifndef NETLIB_BOUNDEDBLOCKINGQUEUE_H
#define NETLIB_BOUNDEDBLOCKINGQUEUE_H

// 有界缓冲区（环形）

#include "Condition.h"
#include "Mutex.h"

#include <boost/circular_buffer.hpp> // boost环形缓冲区
#include <assert.h>

namespace netlib
{

template<typename T>
class BoundedBlockingQueue : noncopyable // 不可拷贝
{
public:
    explicit BoundedBlockingQueue(int maxSize)
    : mutex_(),
      notEmpty_(mutex_),
      notFull_(mutex_),
      queue_(maxSize)
    { }

    void put(const T& x) // 从队列中尾插元素
    {
        MutexLockGuard lock(mutex_);
        while (queue_.full()) // 如果队列满了，需要等待
            notFull_.wait();
        assert(!queue_.full());
        queue_.push_back(x);
        notEmpty_.notify(); // 插入后队列不为空，通知工作线程取出
    }

    void put(T&& x) // 从队列中尾插元素：移动语义（右值引用）
    {
        MutexLockGuard lock(mutex_);
        while (queue_.full())
            notFull_.wait();
        assert(!queue_.full());
        queue_.push_back(std::move(x));
        notEmpty_.notify();
    }

    T take() // 从队列中取出元素
    {
        MutexLockGuard lock(mutex_);
        while (queue_.empty()) // 如果队列为空，需等待有任务到来
            notEmpty_.wait();
        assert(!queue_.empty());
        T front(std::move(queue_.front()));
        queue_.pop_front();
        notFull_.notify(); // 取出后，队列不满，此时通知可以插入新元素
        return front;
    }

    bool empty() const // 判断队列是否为空
    {
        MutexLockGuard lock(mutex_);
        return queue_.empty();
    }

    bool full() const // 判断队列是否已满
    {
        MutexLockGuard lock(mutex_);
        return queue_.full();
    }

    size_t size() const // 返回队列中元素个数
    {
        MutexLockGuard lock(mutex_);
        return queue_.size();
    }

    size_t capacity() const // 返回队列的容量
    {
        MutexLockGuard lock(mutex_);
        return queue_.capacity();
    }

private:
    mutable MutexLock          mutex_;                          // 易变的互斥锁
    Condition                  notEmpty_ GUARDED_BY(mutex_);    // 条件变量（不为空）
    Condition                  notFull_ GUARDED_BY(mutex_);     // 条件变量（没有满）
    boost::circular_buffer<T>  queue_ GUARDED_BY(mutex_);       // boost环形队列

}; // class BoundedBlockingQueue end

} // namespace netlib end

#endif  // netlib_BASE_BOUNDEDBLOCKINGQUEUE_H
